from librpg.util import Position


class MapArea(object):
    """
    MapAreas represent areas that, when entered, moved over or left,
    trigger some event, for example teleport the party from one map to
    another.
    """

    def __init__(self):
        self.area = []

    # Virtual
    def party_entered(self, party_avatar, position):
        """
        *Virtual.*

        Callback called when the PartyAvatar enters the area. *position*
        is the first tile belonging to the area in which *party_avatar*
        first stepped.
        """
        pass

    # Virtual
    def party_moved(self, party_avatar, left_position, entered_position,
                    from_outside):
        """
        *Virtual.*

        Callback called when the PartyAvatar enters any tile in the area.
        This is activated even if *party_avatar* is coming from a tile that
        already belonged to the area. *position* is the entered tile.
        """
        pass

    # Virtual
    def party_left(self, party_avatar, position):
        """
        *Virtual.*

        Callback called when the PartyAvatar leaves the area. *position*
        is the last tile belonging to the area in which *party_avatar*
        stepped.
        """
        pass


class PositionList(object):
    """
    PositionList is a list of positions that may be passed to the
    MapModel.add_area() method specifying where the area should be laid.

    It is intended to be used as a base class to more complex position
    sets.

    The created PositionList will contain all positions generated by
    *iterable*.
    """

    def __init__(self, iterable):
        self.items = [x for x in iterable]

    def __add__(self, iterable):
        return PositionList([x for x in self] + [x for x in iterable])

    def __getitem__(self, index):
        return self.items[index]


class RectangleArea(PositionList):
    """
    A RectangleArea is a PositionList containing all position in a
    rectangular area, ranging from *top_left* to *bottom_right*.

    *top_left* should be a (left, top) tuple, while *bottom_right* should
    be a (right, bottom) tuple. The area will include the *top_left* and
    *bottom_right* positions.
    """

    def __init__(self, top_left, bottom_right):
        self.top = top_left[1]
        self.left = top_left[0]
        self.bottom = bottom_right[1]
        self.right = bottom_right[0]
        self.cur_x = self.left
        self.cur_y = self.top

    def __getitem__(self, index):
        if self.cur_y > self.bottom:
            raise IndexError('Finished')
        result = Position(self.cur_x, self.cur_y)
        self.cur_x += 1
        if self.cur_x > self.right:
            self.cur_x = self.left
            self.cur_y += 1
        return result
